#include <iostream>
#include <time.h>
#include <arpa/inet.h>
#include <termios.h>
#include <fcntl.h>
#include <cstdio>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <stdlib.h>

#include "dataDevice.h"

using namespace std;

const char ConfigFile[]= "config";

/*--------------------ethernetDataDevice-----------------*/
ethernetDataDevice::ethernetDataDevice(char const * addr, int port)
{
	this->addr = addr;
	this->port = port;
}

bool ethernetDataDevice::open()
{
    setFd(socket(AF_INET, SOCK_STREAM, 0));
	if(getFd() == -1)
	{
		cerr<<"create ethernet data device socket file describe error: "<<strerror(errno)<<endl;
		return false;
	}
	
	struct sockaddr_in dataDeviceAddr;
	dataDeviceAddr.sin_family = AF_INET;
	dataDeviceAddr.sin_port = htons(port);
	inet_pton(AF_INET, addr, &dataDeviceAddr.sin_addr);

	if(connect(getFd(), (struct sockaddr*)&dataDeviceAddr, sizeof(struct sockaddr)) == -1)
	{
		cerr<<"connect to "<<addr<<" : "<<port<<" error "<<strerror(errno)<<endl;
		return false;
	}
	
	cout<<"open ethernet device"<<endl;
	return true;
}

ssize_t ethernetDataDevice::read(void *buffer, size_t size)
{
	cout<<"Device: Start reading"<<endl;
	int res = recv(getFd(), buffer, size, 0);
	cout<<"Device: read "<<res<<" bytes from device"<<endl;
	if(res == -1)
	{
    cout<<"reconnecting....."<<endl;
		close(getFd());
		open();
		cout<<"Please send cmd agine"<<endl;
	}
	return res;
}

ssize_t ethernetDataDevice::write(const void *buffer, size_t size)
{
  //char *data = static_cast<char *>(buffer);
	cout<<"Device write"<<endl;
	int res = send(getFd(), buffer, size, 0);
	cout<<"write "<<res<<" bytes to device"<<endl;
	if(res == -1)
	{
		cout<<"reconnecting....."<<endl;
		close(getFd());
		open();
		res = write(buffer, size);
	}
	return res;
}

ethernetDataDevice::~ethernetDataDevice()
{
	close(getFd());
}
/*-------------------serialDataDevice--------------------*/

bool setSpeed(int fd, int speed)
{
	int status;
	struct termios opt;

	if(tcgetattr(fd, &opt) == -1)
	{
		cerr<<"tcgetattr error: "<<strerror(errno)<<endl;
        exit(1);
	}
	/*
	if(tcflush(fd, TCIOFLUSH) == -1)
	{
		cerr<<"tcflush error: "<<strerror(errno)<<endl;
		return false;
	}
	*/
	if(cfsetispeed(&opt, speed) == -1)
	{
		cerr<<"cfsetispeed error: "<<strerror(errno)<<endl;
        exit(1);
	}
	if(cfsetospeed(&opt, speed) == -1)
	{
		cerr<<"cfsetospeed error: "<<strerror(errno)<<endl;
        exit(1);
	}

	if(tcsetattr(fd, TCSANOW, &opt) == -1)
	{
		cerr<<"tcsetattr error: "<<strerror(errno)<<endl;
        exit(1);
	}
	if(tcflush(fd, TCIOFLUSH) == -1)
	{
		cerr<<"tcflush error: "<<strerror(errno)<<endl;
        exit(1);
	}

	return true;
}

bool set_data_format(int fd, int databits, int parity, int stopbits)
{
	//fcntl(fd, F_SETFL, 0);
	struct termios opt;

	if(tcgetattr(fd, &opt) == -1)
	{
		cerr<<"tcgetattr error: "<<strerror(errno)<<endl;
		return false;
	}

	opt.c_cflag &= ~CSIZE;

	switch(databits)
	{
		case 5:
		  opt.c_cflag |= CS5;
			break;
		case 6:
		  opt.c_cflag |= CS6;
			break;
		case 7:
		  opt.c_cflag |= CS7;
			break;
		case 8:
		  opt.c_cflag |= CS8;
			break;
		default:
		  cerr<<"Unsupported data size"<<endl;
			return false;
	}

	switch(parity)
	{
		case 'n':
		case 'N':
		  opt.c_cflag &= ~PARENB;
			opt.c_iflag &= ~INPCK;
			break;
		case 'o':
		case 'O':
		  opt.c_cflag |= (PARODD|PARENB);
			opt.c_iflag |= INPCK;
			break;
		case 'e':
		case 'E':
		  opt.c_cflag |= PARENB;
			opt.c_cflag &= ~PARODD;
			opt.c_iflag |= INPCK;
			break;
		defalut:
		  cerr<<"Unsupported parity"<<endl;
			return false;
	}

	switch(stopbits)
	{
		case 1:
		  opt.c_cflag &= ~CSTOPB;
			break;
		case 2:
		  opt.c_cflag |= ~CSTOPB;
			break;
		default:
		  cerr<<"Unsupported stop bits"<<endl;
			return false;
	}

	/* Set input parity option */
	if(parity != 'n' && parity != 'N')
	  opt.c_iflag |= INPCK;

	opt.c_cflag |= (CLOCAL | CREAD);
  /*
	opt.c_cc[VTIME] = 1; //0.1 seconds
	opt.c_cc[VMIN] = 10;
	*/

	//opt.c_lflag |= (ICANON | ECHO | ECHOE);
	opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  
	if(tcsetattr(fd, TCSANOW, &opt) == -1)
	{
		cerr<<"tcsetattr error: "<<strerror(errno)<<endl;
		return false;
	}

	if(tcflush(fd, TCIFLUSH) == -1)	/* Update the options and do it Now*/
	{
	  cerr<<"tcflush error: "<<strerror(errno)<<endl;
		return false;
	}

  fcntl(fd, F_SETFL, 0);
	return true;
}

serialDataDevice::serialDataDevice(char const * serialName, string speed)
{
	this->serialName = serialName;
    this->speed = speed;
}

bool serialDataDevice::open()
{
    int sspeed;
   
	setFd(::open(serialName, O_RDWR | O_NOCTTY | O_NDELAY));
	if(getFd() == -1)
	{
		cerr<<"Open serial error: "<<strerror(errno)<<endl;
		exit(-1);
	}
	if(!setSpeed(getFd(), B2400))
	  return false;

    if(speed == "2400")
	  setSpeed(getFd(), B2400);
    else if(speed == "9600")
	  setSpeed(getFd(), B9600);
    else if(speed == "115200")
	  setSpeed(getFd(), B115200);
    else
    {
      cerr<<"No such serial speed "<<speed<<endl;
      exit(1);
    }

    cout<<"Open serial "<<serialName<<" success, set speed to "<<speed<<endl;
	if(!set_data_format(getFd(), 8, 'N', 1))
	  return false;
  return true;
}

ssize_t serialDataDevice::read(void *buffer, size_t size)
{
  return ::read(getFd(), buffer, size);
}

ssize_t serialDataDevice::write(const void *buffer, size_t size)
{
	int res = ::write(getFd(), buffer, size);
	cout<<"Device: write "<<res<<" bytes to device"<<endl;
	return res;
}

serialDataDevice::~serialDataDevice()
{
	cout<<"Close serial device"<<endl;
	::close(getFd());
}

/*
int main()
{
	serialDataDevice sdd("/dev/ttySAC2");
	sdd.open();
	//控制实验室壁灯，右边一排，开和关
	char buff1[] ={0x7E, 0x44, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x00, 0x00, 0xFF, 0x70, 0x00, 0x02, 0x00, 0xD3, 0x32, 0x33, 0x34, 0x35, 0xAB, 0x6F, 0x7E};
	char buff2[] ={0x7E, 0x44, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x00, 0x00, 0xFF, 0x70, 0x00, 0x01, 0x00, 0xD3, 0x32, 0x33, 0x34, 0x35, 0x29, 0xB7, 0x7E};
	char buff[100];
	int res;
	while(true)
	{
		sleep(5);
		sdd.write(buff1, sizeof(buff1));
		res = sdd.read(buff, sizeof(buff));
		for(int i=0;i<res;i++)
		  printf("\\x%02x ", buff[i]);
		cout<<endl;
		sleep(5);
		sdd.write(buff2, sizeof(buff2));
		res = sdd.read(buff, sizeof(buff));
		for(int i=0;i<res;i++)
		  printf("\\x%02x ", buff[i]);
		cout<<endl;
	}
	return 0;
}
*/
/*
int main()
{
  serialDataDevice sdd("/dev/ttyTX0");
  if(!sdd.open())
		cout<<"Open serial device error"<<endl;
	cout<<"Open serial device sucess"<<endl;
	char buff[1024];
	int res;
	while(true)
	{
		sdd.write("AT+\x0D\x0A", 5);
		sleep(5);
		bzero(buff, sizeof(buff));
		res = sdd.read(buff, sizeof(buff));
		cout<<buff<<endl;
		cout<<"Read "<<res<<" bytes"<<endl;
		
		for(int i = 0; i<res;i++)
			printf("\\x%02x ", buff[i]);
		cout<<endl;
    
		sdd.write("AT+WSCAN\x0D\x0A", 10);
		sleep(5);
		bzero(buff, sizeof(buff));
		res = sdd.read(buff, sizeof(buff));
		cout<<buff<<endl;
		cout<<"Read "<<res<<" bytes"<<endl;
		
		for(int i = 0; i<res;i++)
			printf("\\x%02x ", buff[i]);
		cout<<endl;
		sleep(10);
	}
}
*/
/*
int main()
{
  ethernetDataDevice edd("126.128.1.108", 3000);
	edd.open();
	char buff1[] = {'\x43', '\x52', '\x49', '\x52', '\x50', '\x53', '\x4D', '\x45', '\x2D', '\x00', '\x00', '\x00', '\x03', '\x01', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00', '\x0C', '\x0B', '\x15', '\x08', '\x36', '\x00', '\x00', '\x00', '\x80', '\x15', '\x86', '\x11', '\x00', '\x00', '\x00', '\x00', '\x40', '\x42', '\x0F', '\x00', '\x01', '\x00', '\x00', '\x00', '\xE5'};
	char buff2[] = {'\x43', '\x52', '\x49', '\x52', '\x50', '\x53', '\x4D', '\x45', '\x15', '\x00', '\x00', '\x00', '\x10', '\x01', '\x00', '\x00', '\x07', '\x00', '\x00', '\x00', '\x97'};
	cout<<edd.write(buff1, sizeof(buff1))<<" bytes"<<endl;
	cout<<"Send cmd1"<<endl;
	sleep(1);
	char buff[1024];
	int res;
	while(true)
	{
		res = edd.read(buff, sizeof(buff));
		cout<<"recv "<<res<<" bytes"<<endl;
    for(int i=0;i<res;i++)
		  printf("\\x%02x ", buff[i]);
		cout<<endl;
	}
	cout<<"Recv data ok"<<endl;
	cout<<edd.write(buff2, sizeof(buff2))<<" bytes"<<endl;
	cout<<"Send stop cmd"<<endl;
}
*/
